﻿using System;

namespace Event
{
    class Program
    {
        public event EventHandler<TestEventArgs> TestEvent;
        static void Main(string[] args)
        {
            CarDealer carDealer = new CarDealer();
            var Jack = new Consumer("Jack");
            carDealer.NewCarInfo += Jack.NewCarIsHere;
            carDealer.NewCar("Benz");

            /**
             * 触发一个事件流程
             * 1. 定义事件
             *      public event EventHandler<TestEventArgs> TestEvent;
             *      event关键字代表定义一个事件
             *      EventHandler<TestEventArgs>代表届时回调事件的泛型必须满足参数类型是TestEventArgs
             *      TestEvent是事件的名称
             * 2. 定义事件对应的EventArgs
             *      class TestEvent:EventArgs
             *      事件对应的EventArgs作为事件触发的参数传递给事件对应回调函数
             *      而且事件对应的EventArgs必须继承自EventArgs
             * 3. 触发事件
             *      self.TestEvent?.Invoke(self, new TestEventArgs("tester"))
             *      ?. 代表判断self.TestEvent是否为空，如果为空就什么都不干；
             *      如果不为空，那么就执行self.TestEvent.Invoke(self, new TestEventArgs("tester"));
             */
            Program self = new Program();
            self.TestEvent += self.TestEventCallback;
            self.TestEvent?.Invoke(self, new TestEventArgs("tester"));

            /**
             * 弱事件
             * 事件的垃圾回收有一个问题，如果侦听器不再直接引用，由于发布程序仍然保留有之前赋值操作的引用
             * 如：
             *      self.TestEvent += self.TestEventCallback;
             * 侦听器是self.TestEventCallback
             * 发布程序是self.TestEvent
             * 上述语句，就讲侦听器的引用复制到了发布程序当中，这样即使侦听器（self.TestEventCallback）销毁，但是由于之前的赋值操作。
             * 导致垃圾回收过程汇总，发现侦听器（self.TestEventCallback）其实在发布程序中还会保留一份引用。
             * 这样便导致了侦听器对应的引用无法被顺利回收。
             *
             * 如何解决：引入弱事件
             */
        }

        public void TestEventCallback(object sender, TestEventArgs e)
        {
            Console.WriteLine("I am {0}", e.Test);
        }
    }

    class TestEventArgs : EventArgs {
        public string Test { private set; get; }
        public TestEventArgs(string test)
        {
            Test = test;
        }
    }
}
